package com.example.blog.modules.system.service.impl;

import com.example.blog.common.exception.ServiceException;
import com.example.blog.common.security.SecurityService;
import com.example.blog.modules.article.entity.Article;
import com.example.blog.modules.article.entity.Comment;
import com.example.blog.modules.article.repository.ArticleRepository;
import com.example.blog.modules.article.repository.CommentRepository;
import com.example.blog.modules.system.dto.NotificationDTO;
import com.example.blog.modules.system.entity.Notification;
import com.example.blog.modules.system.repository.NotificationRepository;
import com.example.blog.modules.system.service.NotificationService;
import com.example.blog.modules.user.entity.User;
import com.example.blog.modules.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class NotificationServiceImpl implements NotificationService {

    private final NotificationRepository notificationRepository;
    private final UserRepository userRepository;
    private final ArticleRepository articleRepository;
    private final CommentRepository commentRepository;
    private final SecurityService securityService;

    @Override
    @Transactional
    public NotificationDTO createNotification(NotificationDTO notificationDTO) {
        Notification notification = new Notification();
        updateNotificationFromDTO(notification, notificationDTO);
        return convertToDTO(notificationRepository.save(notification));
    }

    @Override
    @Transactional
    public void deleteNotification(Long id) {
        Notification notification = notificationRepository.findById(id)
                .orElseThrow(() -> new ServiceException("通知不存在"));
        
        // 检查权限
        if (!securityService.isCurrentUser(notification.getUser().getId()) && 
            !securityService.hasRole("ROLE_ADMIN")) {
            throw new ServiceException("没有权限删除此通知");
        }
        
        notificationRepository.delete(notification);
    }

    @Override
    @Transactional(readOnly = true)
    public NotificationDTO getNotification(Long id) {
        return convertToDTO(notificationRepository.findById(id)
                .orElseThrow(() -> new ServiceException("通知不存在")));
    }

    @Override
    @Transactional(readOnly = true)
    public Page<NotificationDTO> getUserNotifications(Long userId, Boolean isRead, Pageable pageable) {
        if (isRead != null) {
            return notificationRepository.findByUserIdAndIsRead(userId, isRead, pageable)
                    .map(this::convertToDTO);
        }
        return notificationRepository.findByUserId(userId, pageable)
                .map(this::convertToDTO);
    }

    @Override
    @Transactional(readOnly = true)
    public long getUnreadCount(Long userId) {
        return notificationRepository.countByUserIdAndIsRead(userId, false);
    }

    @Override
    @Transactional
    public void markAsRead(Long id) {
        Notification notification = notificationRepository.findById(id)
                .orElseThrow(() -> new ServiceException("通知不存在"));
        notification.setIsRead(true);
        notificationRepository.save(notification);
    }

    @Override
    @Transactional
    public void markAllAsRead(Long userId) {
        notificationRepository.markAllAsRead(userId);
    }

    @Override
    @Transactional
    public void deleteAllRead(Long userId) {
        notificationRepository.deleteAllReadByUserId(userId);
    }

    @Override
    @Transactional
    public void sendSystemNotification(String title, String content, String type) {
        NotificationDTO dto = new NotificationDTO();
        dto.setTitle(title);
        dto.setContent(content);
        dto.setType(type);
        dto.setIsSystem(true);
        dto.setLevel(2);  // 系统通知默认为紧急级别
        createNotification(dto);
    }

    @Override
    @Transactional
    public void sendUserNotification(Long userId, String title, String content, String type) {
        NotificationDTO dto = new NotificationDTO();
        dto.setTitle(title);
        dto.setContent(content);
        dto.setType(type);
        dto.setUserId(userId);
        dto.setLevel(0);  // 用户通知默认为普通级别
        createNotification(dto);
    }

    @Override
    @Transactional
    public void sendCommentNotification(Long userId, Long articleId, Long commentId) {
        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new ServiceException("文章不存在"));
        Comment comment = commentRepository.findById(commentId)
                .orElseThrow(() -> new ServiceException("评论不存在"));
        
        NotificationDTO dto = new NotificationDTO();
        dto.setTitle("新评论通知");
        dto.setContent(String.format("您的文章《%s》收到了新评论：%s", 
                article.getTitle(), comment.getContent()));
        dto.setType("COMMENT");
        dto.setUserId(userId);
        dto.setTargetType("ARTICLE");
        dto.setTargetId(articleId);
        dto.setLevel(1);  // 评论通知默认为重要级别
        
        createNotification(dto);
    }

    @Override
    @Transactional
    public void sendLikeNotification(Long userId, String targetType, Long targetId) {
        String title = "点赞通知";
        String content;
        
        switch (targetType) {
            case "ARTICLE":
                Article article = articleRepository.findById(targetId)
                        .orElseThrow(() -> new ServiceException("文章不存在"));
                content = String.format("您的文章《%s》收到了新的点赞", article.getTitle());
                break;
            case "COMMENT":
                Comment comment = commentRepository.findById(targetId)
                        .orElseThrow(() -> new ServiceException("评论不存在"));
                content = "您的评论收到了新的点赞";
                break;
            default:
                throw new ServiceException("不支持的目标类型");
        }
        
        NotificationDTO dto = new NotificationDTO();
        dto.setTitle(title);
        dto.setContent(content);
        dto.setType("LIKE");
        dto.setUserId(userId);
        dto.setTargetType(targetType);
        dto.setTargetId(targetId);
        dto.setLevel(0);  // 点赞通知默认为普通级别
        
        createNotification(dto);
    }

    @Override
    @Transactional
    public void sendFollowNotification(Long userId, Long followerId) {
        User follower = userRepository.findById(followerId)
                .orElseThrow(() -> new ServiceException("用户不存在"));
        
        NotificationDTO dto = new NotificationDTO();
        dto.setTitle("新粉丝通知");
        dto.setContent(String.format("用户 %s 关注了您", follower.getNickname()));
        dto.setType("FOLLOW");
        dto.setUserId(userId);
        dto.setTargetType("USER");
        dto.setTargetId(followerId);
        dto.setLevel(1);  // 关注通知默认为重要级别
        
        createNotification(dto);
    }

    private void updateNotificationFromDTO(Notification notification, NotificationDTO dto) {
        notification.setTitle(dto.getTitle());
        notification.setContent(dto.getContent());
        notification.setType(dto.getType());
        notification.setTargetType(dto.getTargetType());
        notification.setTargetId(dto.getTargetId());
        notification.setLevel(dto.getLevel());
        
        if (dto.getUserId() != null) {
            User user = userRepository.findById(dto.getUserId())
                    .orElseThrow(() -> new ServiceException("用户不存在"));
            notification.setUser(user);
        }
        
        if (dto.getIsSystem() != null) {
            notification.setIsSystem(dto.getIsSystem());
        }
    }

    private NotificationDTO convertToDTO(Notification notification) {
        NotificationDTO dto = new NotificationDTO();
        dto.setId(notification.getId());
        dto.setTitle(notification.getTitle());
        dto.setContent(notification.getContent());
        dto.setType(notification.getType());
        dto.setIsRead(notification.getIsRead());
        dto.setTargetType(notification.getTargetType());
        dto.setTargetId(notification.getTargetId());
        dto.setLevel(notification.getLevel());
        dto.setIsSystem(notification.getIsSystem());
        dto.setCreateTime(notification.getCreateTime());
        dto.setUpdateTime(notification.getUpdateTime());
        
        if (notification.getUser() != null) {
            dto.setUser(convertToUserDTO(notification.getUser()));
            dto.setUserId(notification.getUser().getId());
        }
        
        return dto;
    }

    private com.example.blog.modules.user.dto.UserDTO convertToUserDTO(User user) {
        com.example.blog.modules.user.dto.UserDTO dto = new com.example.blog.modules.user.dto.UserDTO();
        dto.setId(user.getId());
        dto.setUsername(user.getUsername());
        dto.setNickname(user.getNickname());
        dto.setAvatar(user.getAvatar());
        return dto;
    }
} 